/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package idea.sfo.viewer.graphics;


import designersfo.Cons.CellInfo.CellFormat;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.NoSuchElementException;


/**
 * The Content Layout class handles placing the content (text, graphic, etc )
 * into the parent window.
 * <p/>
 * Based on the <a
 * href="https://censuswiki.fenestra.com/bin/view/Main/HorizontalAlignmentEnum">
 * Horizontal alignment enumeration spec</a>. The horizontal alignment
 * enumeration comprises three keyword values, each of which represents how an
 * item is positioned with respect to its container's boundaries:
 * <p/>
 * <DL>
 * <DT>left</DT><DD> position the item at the left side of its container; for
 * text, render the text left-justified.</DD>
 * <DT>center</DT><DD> position the item at the horizontal center of its
 * container; for text, render the text centered.</DD>
 * <DT>right</DT><DD> position the item at the right side of its container; for
 * text, render the text right-justified.</DD>
 * </DL>
 *
 * Based on the <a
 * href="https://censuswiki.fenestra.com/bin/view/Main/VerticalAlignmentEnum">
 * Vertical alignment enumeration spec</a>. The vertical alignment enumeration
 * comprises three keyword values, each of which represents how an item is
 * positioned with respect to its container's boundaries:
 * <p/>
 * <DL>
 * <DT>top</DT><DD> position the item at the top of its container.</DD>
 * <DT>center</DT><DD> position the item at the vertical center of its
 * container.</DD>
 * <DT>bottom</DT><DD> position the item at the bottom of its container.</DD>
 * </DL>
 *
 * NOTES: The keywords are case-sensitive.
 * <p/>
 * @author renke002 - massimo.renke@census.gov
 */
public abstract class ContentLayout implements Drawable
{

    /**
     * Position the item at the left side of its container; for text, render the
     * text left-justified.
     */
    public static final String HORIZONTAL_NAME_LEFT = "left";
    /**
     * Position the item at the horizontal center of its container; for text,
     * render the text centered.
     */
    public static final String HORIZONTAL_NAME_CENTER = "center";
    /**
     * Position the item at the right side of its container; for text, render
     * the text right-justified.
     */
    public static final String HORIZONTAL_NAME_RIGHT = "right";
    /**
     * Position the item at the top of its container.
     */
    public static final String VERTICAL_NAME_TOP = "top";
    /**
     * Position the item at the vertical center of its container.
     */
    public static final String VERTICAL_NAME_CENTER = "center";
    /**
     * Position the item at the bottom of its container.
     */
    public static final String VERTICAL_NAME_BOTTOM = "bottom";
    /**
     * Vertical alignment setting for this object.
     */
    private String horzAlign;
    /**
     * Horizontal alignment setting for this object.
     */
    private String vertAlign;


    /**
     * Align the content of given dimensions within the parent container based
     * on the horizontal and vertical alignment values.
     * <p/>
     * @param parent    Parent container, the rectangle provides the initial top
     *                  left corner point and the dimensions that the content
     *                  needs to fit inside.
     * <p/>
     * @param content   Dimensions of the content that needs to fit inside the
     *                  parent.
     * <p/>
     * @param horzAlign Horizontal alignment value.
     * <p/>
     * @param vertAlign Vertical alignment value.
     * <p/>
     * @return Point with coordinates for the top left corner of the rectangle
     *         that will hold the content.
     * <p/>
     * @throws IllegalArgumentException If the size of the content exceeds that
     *                                  of the parent cell.
     * <p/>
     * @throws NoSuchElementException   If the horizontal or vertical alignment
     *                                  values are not allowed by the system.
     */
    private static Point alignContent(
            Rectangle parent ,
            Dimension content ,
            String horzAlign ,
            String vertAlign )
            throws IllegalArgumentException , NoSuchElementException
    {
        if ( parent.height < content.height || parent.width < content.width )
        {
            // the content cannot fit inside the parent.
            throw new IllegalArgumentException(
                    "Content size exceeds that of parent cell." );
        }

        int topLeftX = ContentLayout.alignContentHoriz( parent , content ,
                horzAlign );

        int topLeftY = ContentLayout.alignContentVert( parent , content ,
                vertAlign );

        return new Point( topLeftX , topLeftY );
    }


    /**
     * Calculate the X-coordinate to horizontally align the content of given
     * dimensions within the parent container based on the horizontal alignment
     * values.
     * <p/>
     * @param container Parent container, the rectangle provides the initial top
     *                  left corner point and the dimensions that the content
     *                  needs to fit inside.
     * <p/>
     * @param content   Dimensions of the content that needs to fit inside the
     *                  parent.
     * <p/>
     * @param horzAlign Horizontal alignment value.
     * <p/>
     * @return X-coordinate for the top left corner of the rectangle that will
     *         hold the content.
     * <p/>
     * @throws IllegalArgumentException If the width of the content exceeds that
     *                                  of the parent cell.
     * <p/>
     * @throws NoSuchElementException   If the horizontal alignment values are
     *                                  not allowed by the system.
     */
    private static int alignContentHoriz( Rectangle container , Dimension content , String horzAlign )
            throws IllegalArgumentException , NoSuchElementException
    {
        if ( container.width < content.width )
        {
            // the content cannot fit inside the parent.
            throw new IllegalArgumentException(
                    "Content width exceeds that of parent cell."
                    + "(" + content.width + " > " + container.width + ")" );
        }
        else if ( container.width == content.width )
        {
            /*
             * The parent container and the content have the same width: there
             * is no alignment to calculate since the content takes up all the
             * available space.
             */
            return container.x;
        }

        int topLeftX = 0;

        /*
         * Calculate the X-value for the top left point of the rectangle that
         * will hold this cell's content.
         */
        switch ( horzAlign )
        {
            case ContentLayout.HORIZONTAL_NAME_CENTER:
                /*
                 * Position the item at the horizontal center of its container;
                 */
                topLeftX = container.x + ( container.width - content.width ) / 2;
                break;
            case ContentLayout.HORIZONTAL_NAME_LEFT:
                /*
                 * Position the item at the left side of its container;
                 */
                topLeftX = container.x;
                break;
            case ContentLayout.HORIZONTAL_NAME_RIGHT:
                /**
                 * Position the item at the right side of its container;
                 */
                topLeftX = container.x + ( container.width - content.width );
                break;
            default:
                throw new NoSuchElementException(
                        "The Horizontal Alignment value: "
                        + horzAlign + " is not supported by the system." );
        }
        return topLeftX;
    }


    /**
     * Calculate the Y-coordinate to vertically align the content of given
     * dimensions within the parent container based on the vertical alignment
     * values.
     * <p/>
     * @param parent    Parent container, the rectangle provides the initial top
     *                  left corner point and the dimensions that the content
     *                  needs to fit inside.
     * <p/>
     * @param content   Dimensions of the content that needs to fit inside the
     *                  parent.
     * <p/>
     * @param vertAlign Vertical alignment value.
     * <p/>
     * @return Y-coordinate for the top left corner of the rectangle that will
     *         hold the content.
     * <p/>
     * @throws IllegalArgumentException If the height of the content exceeds
     *                                  that of the parent cell.
     * <p/>
     * @throws NoSuchElementException   If the horizontal or vertical alignment
     *                                  values are not allowed by the system.
     */
    private static int alignContentVert( Rectangle parent , Dimension content , String vertAlign )
            throws IllegalArgumentException , NoSuchElementException
    {
        if ( parent.height < content.height )
        {
            // the content cannot fit inside the parent.
            throw new IllegalArgumentException(
                    "Content height exceeds that of parent cell. "
                    + "(" + content.height + " > " + parent.height + ")" );
        }
        else if ( parent.height == content.height )
        {
            /*
             * The parent container and the content have the same height: there
             * is no alignment to calculate since the content takes up all the
             * available space.
             */
            return parent.y;
        }

        int topLeftY = 0;
        /*
         * Calculate the Y-value for the top left point of the rectangle that
         * will hold this cell's content.
         */
        switch ( vertAlign )
        {
            case ContentLayout.VERTICAL_NAME_BOTTOM:
                /*
                 * Position the item at the bottom of its container.
                 */
                topLeftY = parent.y + ( parent.height - content.height );
                break;
            case ContentLayout.VERTICAL_NAME_CENTER:
                /*
                 * Position the item at the vertical center of its container.
                 */
                topLeftY = parent.y + ( parent.height - content.height ) / 2;
                break;
            case ContentLayout.VERTICAL_NAME_TOP:
                /*
                 * Position the item at the top of its container.
                 */
                topLeftY = parent.y;
                break;
            default:
                throw new NoSuchElementException(
                        "The Vertical Alignment value: "
                        + vertAlign + " is not supported by the system." );
        }

        return topLeftY;
    }


    /**
     *
     * @return
     */
    public String getLabel()
    {
        return "...";
    }


    /**
     * Align the content of given dimensions within the parent container based
     * on the values defined in the CellFormat element.
     * <p/>
     * @param parent  Parent container, the rectangle provides the initial top
     *                left corner point and the dimensions that the content
     *                needs to fit inside.
     * <p/>
     * @param content Dimensions of the content that needs to fit inside the
     *                parent.
     * <p/>
     * @param cf      CellFormat SFO element containing layout values for the
     *                cell.
     * <p/>
     * @return Point with coordinates for the top left corner of the rectangle
     *         that will hold the content.
     * <p/>
     * @throws IllegalArgumentException If the size of the content exceeds that
     *                                  of the parent cell.
     * <p/>
     * @throws NoSuchElementException   If the alignment values specified in the
     *                                  CellFormat SFO element are not allowed
     *                                  by the system.
     */
    public static Point placeContent(
            Rectangle parent , Dimension content , CellFormat cf )
            throws IllegalArgumentException , NoSuchElementException
    {
        /*
         * required: indicates the horizontal alignment of the content within
         * the cell
         */
        String horzAlign = cf.getHorzAlignment();
        /*
         * required: indicates the vertical alignment of the content within the
         * cell
         */
        String vertAlign = cf.getVertAlignment();

        return ContentLayout.alignContent( parent , content , horzAlign ,
                vertAlign );
    }


    /**
     * Align the content of given dimensions within the parent container based
     * on the values defined in the CellFormat element.
     * <p/>
     * @param parent    Parent container, the rectangle provides the initial top
     *                  left corner point and the dimensions that the content
     *                  needs to fit inside.
     * <p/>
     * @param content   Dimensions of the content that needs to fit inside the
     *                  parent.
     * <p/>
     * @param horzAlign Horizontal alignment for the content.
     * <p/>
     * @param vertAlign Vertical alignment for the content.
     * <p/>
     * @return Point with coordinates for the top left corner of the rectangle
     *         that will hold the content.
     * <p/>
     * @throws IllegalArgumentException If the size of the content exceeds that
     *                                  of the parent cell.
     * <p/>
     * @throws NoSuchElementException   If the alignment values specified in the
     *                                  CellFormat SFO element are not allowed
     *                                  by the system.
     */
    public static Point placeContent(
            Rectangle parent , Dimension content ,
            String horzAlign , String vertAlign )
            throws IllegalArgumentException , NoSuchElementException
    {
        return ContentLayout.alignContent( parent , content , horzAlign ,
                vertAlign );
    }


    /**
     *
     * @return
     */
    public void setLabel( String label )
    {
        System.out.println( label );
    }

}
